Completed
Push — master ( 641a91...fc9f6a )
by
unknown
10:16
created

angular.controller(ꞌCredentialEditCtrlꞌ)   C

Complexity

Conditions 8
Paths 3073

Size

Total Lines 325

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
dl 0
loc 325
rs 5.1333
c 0
b 0
f 0
nc 3073
nop 12

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
/**
2
 * Nextcloud - passman
3
 *
4
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
5
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
(function () {
24
	'use strict';
25
26
27
	/**
28
	 * @ngdoc function
29
	 * @name passmanApp.controller:MainCtrl
30
	 * @description
31
	 * # MainCtrl
32
	 * Controller of the passmanApp
33
	 */
34
	angular.module('passmanApp')
35
		.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', 'NotificationService', 'ShareService', '$translate',
36
			function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService, NotificationService, ShareService, $translate) {
37
				$scope.active_vault = VaultService.getActiveVault();
38
				if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
39
					if (!$scope.active_vault) {
40
						$location.path('/');
41
						return;
42
					}
43
				} else {
44
					if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
45
						var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
46
						_vault.vaultKey = SettingsService.getSetting('defaultVaultPass');
47
						VaultService.setActiveVault(_vault);
48
						$scope.active_vault = _vault;
49
					}
50
				}
51
52
				VaultService.getVault($scope.active_vault).then(function (vault) {
53
					vault.vaultKey = VaultService.getActiveVault().vaultKey;
54
					delete vault.credentials;
55
					VaultService.setActiveVault(vault);
56
					$scope.pwSettings = VaultService.getVaultSetting('pwSettings',
57
						{
58
							'length': 12,
59
							'useUppercase': true,
60
							'useLowercase': true,
61
							'useDigits': true,
62
							'useSpecialChars': true,
63
							'minimumDigitCount': 3,
64
							'avoidAmbiguousCharacters': false,
65
							'requireEveryCharType': true,
66
							'generateOnCreate': true
67
						});
68
				});
69
70
				$scope.currentTab = {
71
					title: $translate.instant('general'),
72
					url: 'views/partials/forms/edit_credential/basics.html',
73
					color: 'blue'
74
				};
75
				$scope.otpType = 'qrcode';
76
				$translate(['general', 'password', 'custom.fields','files','otp']).then(function (translations) {
77
					$scope.tabs = [{
78
						title: translations.general,
79
						url: 'views/partials/forms/edit_credential/basics.html',
80
						color: 'blue'
81
					}, {
82
						title: translations.password,
83
						url: 'views/partials/forms/edit_credential/password.html',
84
						color: 'green'
85
					}, {
86
						title:translations['custom.fields'],
87
						url: 'views/partials/forms/edit_credential/custom_fields.html',
88
						color: 'orange'
89
					}, {
90
						title: translations.files,
91
						url: 'views/partials/forms/edit_credential/files.html',
92
						color: 'yellow'
93
					}, {
94
						title: translations.otp,
95
						url: 'views/partials/forms/edit_credential/otp.html',
96
						color: 'purple'
97
					}];
98
					$scope.currentTab = $scope.tabs[0];
99
				});
100
101
				if ($scope.active_vault) {
102
					$scope.$parent.selectedVault = true;
103
				}
104
				var storedCredential = SettingsService.getSetting('edit_credential');
105
106
				if (!storedCredential) {
107
					CredentialService.getCredential($routeParams.credential_id).then(function (result) {
108
						$scope.storedCredential = CredentialService.decryptCredential(angular.copy(result));
109
					});
110
				} else {
111
					$scope.storedCredential = CredentialService.decryptCredential(angular.copy(storedCredential));
112
					$scope.storedCredential.password_repeat = angular.copy($scope.storedCredential.password);
113
					$scope.storedCredential.expire_time = $scope.storedCredential.expire_time * 1000;
114
				}
115
116
				$scope.getTags = function ($query) {
117
					return TagService.searchTag($query);
118
				};
119
120
121
				$scope.onClickTab = function (tab) {
122
					$scope.currentTab = tab;
123
				};
124
125
				$scope.isActiveTab = function (tab) {
126
					return tab.url === $scope.currentTab.url;
127
				};
128
129
				/**
130
				 * Below general edit functions
131
				 */
132
133
				$scope.pwGenerated = function (pass) {
134
					$scope.storedCredential.password_repeat = pass;
135
				};
136
137
138
				var _customField = {
139
					label: '',
140
					value: '',
141
					secret: false,
142
					field_type: 'text'
143
				};
144
				$scope.selected_field_type = 'text';
145
				$scope.new_custom_field = angular.copy(_customField);
146
147
				$scope.addCustomField = function () {
148
					var _field = angular.copy($scope.new_custom_field);
149
					if (!_field.label) {
150
						NotificationService.showNotification($translate.instant('error.no.label'), 3000);
151
					}
152
					if (!_field.value) {
153
						NotificationService.showNotification($translate.instant('error.no.value'), 3000);
154
					}
155
					if (!_field.label || !_field.value) {
156
						return;
157
					}
158
					$scope.selected_field_type = 'text';
159
					_field.secret = (_field.field_type === 'password');
160
					if(_field.field_type === 'file'){
161
						var key = false;
162
						var _file = $scope.new_custom_field.value;
163
						if (!$scope.storedCredential.hasOwnProperty('acl') && $scope.storedCredential.hasOwnProperty('shared_key')) {
164
165
							if ($scope.storedCredential.shared_key) {
166
								key = EncryptService.decryptString(angular.copy($scope.storedCredential.shared_key));
167
							}
168
						}
169
170
						if ($scope.storedCredential.hasOwnProperty('acl')) {
171
							key = EncryptService.decryptString(angular.copy($scope.storedCredential.acl.shared_key));
172
						}
173
174
						FileService.uploadFile(_file, key).then(function (result) {
175
							delete result.file_data;
176
							result.filename = EncryptService.decryptString(result.filename, key);
177
							_field.value = result;
178
							$scope.storedCredential.custom_fields.push(_field);
179
							$scope.new_custom_field = angular.copy(_customField);
180
						});
181
					} else {
182
						$scope.storedCredential.custom_fields.push(_field);
183
						$scope.new_custom_field = angular.copy(_customField);
184
					}
185
186
				};
187
188
				$scope.addFileToCustomField = function (file) {
189
          $scope.new_custom_field.value = {
190
            filename: file.name,
191
            size: file.size,
192
            mimetype: file.type,
193
            data: file.data
194
          };
195
					$scope.$digest();
196
				};
197
198
				$scope.deleteCustomField = function (field) {
199
					if(field.hasOwnProperty('field_type')) {
200
						if (field.field_type === 'file') {
201
							FileService.deleteFile(field.value);
202
						}
203
					}
204
					var idx = $scope.storedCredential.custom_fields.indexOf(field);
205
					$scope.storedCredential.custom_fields.splice(idx, 1);
206
				};
207
208
				$scope.new_file = {
209
					name: '',
210
					data: null
211
				};
212
213
				$scope.deleteFile = function (file) {
214
					var idx = $scope.storedCredential.files.indexOf(file);
215
					FileService.deleteFile(file).then(function () {
216
						$scope.storedCredential.files.splice(idx, 1);
217
					});
218
				};
219
220
				$scope.fileLoaded = function (file) {
221
					var key;
222
					var _file = {
223
						filename: file.name,
224
						size: file.size,
225
						mimetype: file.type,
226
						data: file.data
227
					};
228
229
					if (!$scope.storedCredential.hasOwnProperty('acl') && $scope.storedCredential.hasOwnProperty('shared_key')) {
230
231
						if ($scope.storedCredential.shared_key) {
232
							key = EncryptService.decryptString(angular.copy($scope.storedCredential.shared_key));
233
						}
234
					}
235
236
					if ($scope.storedCredential.hasOwnProperty('acl')) {
237
						key = EncryptService.decryptString(angular.copy($scope.storedCredential.acl.shared_key));
238
					}
239
240
241
					FileService.uploadFile(_file, key).then(function (result) {
242
						delete result.file_data;
243
						result.filename = EncryptService.decryptString(result.filename, key);
0 ignored issues
show
Bug introduced by
The variable key seems to not be initialized for all possible execution paths. Are you sure decryptString handles undefined variables?
Loading history...
244
						$scope.storedCredential.files.push(result);
245
					});
246
247
248
					$scope.$digest();
249
				};
250
251
				$scope.fileLoadError = function (error) {
252
					console.log($translate.instant('error.loading.file'), error);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
253
				};
254
255
				$scope.selected_file = '';
256
				$scope.fileprogress = [];
257
				$scope.fileSelectProgress = function (progress) {
258
					if (progress) {
259
						$scope.fileprogress = progress;
260
						$scope.$digest();
261
262
					}
263
				};
264
				$scope.renewIntervalValue = 0;
265
				$scope.renewIntervalModifier = '0';
266
267
				$scope.updateInterval = function (renewIntervalValue, renewIntervalModifier) {
268
					var value = parseInt(renewIntervalValue);
269
					var modifier = parseInt(renewIntervalModifier);
270
					if (value && modifier) {
271
						$scope.storedCredential.renew_interval = value * modifier;
272
					}
273
				};
274
275
				$scope.parseQR = function (QRCode) {
276
					if (!QRCode) {
277
						NotificationService.showNotification($translate.instant('invalid.qr'), 5000);
278
						return;
279
					}
280
					/** global: URL */
281
					var uri = new URL(QRCode.qrData);
282
					var type = (uri.href.indexOf('totp/') !== -1) ? 'totp' : 'hotp';
283
					var label = uri.pathname.replace('//'+ type +'/', '');
284
					$scope.storedCredential.otp = {
285
						type: type,
286
						label: decodeURIComponent(label),
287
						qr_uri: QRCode,
288
						issuer: uri.searchParams.get('issuer'),
289
						secret: uri.searchParams.get('secret')
290
					};
291
					$scope.$digest();
292
				};
293
				$scope.saving = false;
294
				$scope.saveCredential = function () {
295
          $scope.saving = true;
296
297
298
					if ($scope.new_custom_field.label && $scope.new_custom_field.value) {
299
						$scope.storedCredential.custom_fields.push(angular.copy($scope.new_custom_field));
300
					}
301
302
303
					if ($scope.storedCredential.password !== $scope.storedCredential.password_repeat){
304
            $scope.saving = false;
305
            NotificationService.showNotification($translate.instant('password.do.not.match'), 5000);
306
						return;
307
					}
308
309
					//@TODO  validation
310
					//@TODO When credential is expired and has renew interval set, calc new expire time.
311
					delete $scope.storedCredential.password_repeat;
312
					
313
					if (!$scope.storedCredential.credential_id) {
314
						$scope.storedCredential.vault_id = $scope.active_vault.vault_id;
315
						CredentialService.createCredential($scope.storedCredential).then(function () {
316
              $scope.saving = false;
317
							$location.path('/vault/' + $routeParams.vault_id);
318
							NotificationService.showNotification($translate.instant('credential.created'), 5000);
319
320
						});
321
					} else {
322
323
						var key, _credential;
324
						if (!$scope.storedCredential.hasOwnProperty('acl') && $scope.storedCredential.hasOwnProperty('shared_key')) {
325
326
							if ($scope.storedCredential.shared_key) {
327
								key = EncryptService.decryptString(angular.copy($scope.storedCredential.shared_key));
328
							}
329
						}
330
331
						if ($scope.storedCredential.hasOwnProperty('acl')) {
332
							key = EncryptService.decryptString(angular.copy($scope.storedCredential.acl.shared_key));
333
						}
334
335
						if (key) {
336
							_credential = ShareService.encryptSharedCredential($scope.storedCredential, key);
337
						} else {
338
							_credential = angular.copy($scope.storedCredential);
339
						}
340
341
						delete _credential.shared_key;
342
						var _useKey = (key != null);
0 ignored issues
show
Bug introduced by
The variable key seems to not be initialized for all possible execution paths.
Loading history...
Coding Style introduced by
It is recommended to use !== to compare with null.

Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator.

Read more about comparison operations.

Loading history...
343
						var regex = /(<([^>]+)>)/ig;
344
						if(_credential.description && _credential.description !== "") {
345
							_credential.description = _credential.description.replace(regex, "");
346
						}
347
						CredentialService.updateCredential(_credential, _useKey).then(function () {
348
              $scope.saving = false;
349
							SettingsService.setSetting('edit_credential', null);
350
							$location.path('/vault/' + $routeParams.vault_id);
351
							NotificationService.showNotification($translate.instant('credential.updated'), 5000);
352
						});
353
					}
354
355
				};
356
357
				$scope.cancel = function () {
358
					$location.path('/vault/' + $routeParams.vault_id);
359
				};
360
			}]);
361
}());